﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ScriptCoreLib;
using AvalonTycoonMansion.Shared.Isometric;
using ScriptCoreLib.Shared.Lambda;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows;
using ScriptCoreLib.Shared.Avalon.Extensions;
using System.Windows.Threading;

namespace AvalonTycoonMansion.Shared
{
	[Script]
	public class PlaygroundBuilder
	{
		public IsometricContainer Playground;
		public KnownTileDescriptions Descriptions;

		public void Animate()
		{
			foreach (var u in Playground.Where(k => k.Description == Descriptions.Dirt))
			{
				if (u.FuzzyAge % 4 >= 3)
					u.Description = Descriptions.DirtDirtGrass;
			}

			foreach (var u in Playground.Where(k => k.Description == Descriptions.DirtDirtGrass))
			{
				if (u.FuzzyAge % 4 >= 3)
					u.Description = Descriptions.DirtGrassGrass;
			}

			foreach (var u in Playground.Where(k => k.Description == Descriptions.DirtGrassGrass))
			{
				if (u.FuzzyAge % 4 >= 3)
					u.Description = Descriptions.Grass;
			}

			foreach (var u in from k in Playground
							  where k.Description != null
							  where k.Description.AnimationNextFrame != null
							  where k.Age >= k.Description.AnimationDelay
							  let AnimationNextFrame = k.Description.AnimationNextFrame()
							  where AnimationNextFrame != null

							  select new { k, AnimationNextFrame })
			{
				u.k.Description = u.AnimationNextFrame;
			}

			foreach (var u in Playground)
			{
				u.Age++;
			}
		}

		public void RailsX(int y)
		{
			Playground.Where(k => k.Y == y).ForEach(k => k.Description = Descriptions.RailsX);

		}

		public void RoadX(int y)
		{
			Playground.Where(k => k.Y == y).ForEach(
				k =>
				{
					if (k.Description == Descriptions.RoadY)
						k.Description = Descriptions.RoadXY;
					else
						k.Description = Descriptions.RoadX;
				}
			);
		}

		public void RoadY(int x)
		{
			Playground.Where(k => k.X == x).ForEach(
				k =>
				{
					if (k.Description == Descriptions.RailsX)
					{
						k.Description = Descriptions.RailsXRoad;
						return;
					}

					if (k.Description == Descriptions.RoadX)
					{
						k.Description = Descriptions.RoadXY;
						return;
					}


					if (k.Description == Descriptions.Grass102)
					{
						k.Description = Descriptions.RoadX102;
						return;
					}


					k.Description = Descriptions.RoadY;
				}
			);
		}

		public void RaiseLand(int x, int y, int cx, int cy, int levels)
		{
			RaiseLand(x, y, cx, cy);

			if (levels > 0)
				if (cx > 4)
					if (cy > 4)
						RaiseLand(x + 1, y + 1, cx - 2, cy - 2, levels - 1);
		}

		public void RaiseLand(int x, int y, int cx, int cy)
		{
			#region low
			Playground[x, y].Description = Descriptions.Grass104;

			for (int i = 1; i < cx - 1; i++)
				Playground[x + i, y].Description = Descriptions.Grass105;

			Playground[x + cx - 1, y].Description = Descriptions.Grass103;
			#endregion

			var Altitude = Playground[x, y].Altitude;

			for (int i = 0; i < cx; i++)
				for (int j = 0; j < cy; j++)
				{
					Playground[x + i, y + j].Altitude = Altitude + 8;
					//Playground[x + i, y + j].Description = Descriptions.Grass;
				}

			#region hi
			Playground[x, y + cy - 1].Description = Descriptions.Grass107;

			for (int i = 1; i < cx - 1; i++)
				Playground[x + i, y + cy - 1].Description = Descriptions.Grass102;

			Playground[x + cx - 1, y + cy - 1].Description = Descriptions.Grass100;
			#endregion

			for (int j = 1; j < cy - 1; j++)
			{
				Playground[x, y + j].Description = Descriptions.Grass106;
				Playground[x + cx - 1, y + j].Description = Descriptions.Grass101;
			}

		}

		public void ShowCorners(int x, int y)
		{
			var RedPosition = Playground.ToIsometricPosition(x + .1, y - .1);
			RedPosition.X -= 2;
			RedPosition.Y -= 2;

			var RedCanvas = new Canvas
			{
				Width = 4,
				Height = IsometricContainerTile.TileHeight / 3 - 4,
				Background = Brushes.Red,
				Opacity = 0.5,
			}
				.AttachTo(Playground.Content)
				.MoveTo(RedPosition);

			Panel.SetZIndex(RedCanvas, Convert.ToInt32(RedPosition.Y) + this.Playground.Height + IsometricContainerTile.TileHeight / 2 - 1);

			var BluePosition = Playground.ToIsometricPosition(x + .9, y - .1);

			BluePosition.X -= IsometricContainerTile.TileWidth / 6;
			BluePosition.Y -= 2;

			var BlueCanvas = new Canvas
			{
				Width = IsometricContainerTile.TileWidth / 3,
				Height = 4,
				Background = Brushes.Blue,
				Opacity = 0.5
			}
				.AttachTo(Playground.Content)
				.MoveTo(BluePosition);

			Panel.SetZIndex(BlueCanvas, Convert.ToInt32(BluePosition.Y) + this.Playground.Height);

			var YellowPosition = Playground.ToIsometricPosition(x + .1, y - .9);
			YellowPosition.X -= IsometricContainerTile.TileWidth / 6;
			YellowPosition.Y -= 2;

			var YellowCanvas = new Canvas
			{
				Width = IsometricContainerTile.TileWidth / 3,
				Height = 4,
				Background = Brushes.Yellow,
				Opacity = 0.5

			}
				.AttachTo(Playground.Content)
				.MoveTo(YellowPosition);

			Panel.SetZIndex(YellowCanvas, Convert.ToInt32(YellowPosition.Y) + this.Playground.Height + IsometricContainerTile.TileHeight / 2);

		}

		public bool AddBusXDisabled = true;
		public void AddBusX(double x, double y)
		{
			if (AddBusXDisabled)
				return;

			var Bus1x = x;

			var Bus1 = new IsometricContainer.Sprite(Playground, 20, 16)
				{
					Altitude = -4
				};

			new Image
			{
				Source = (KnownAssets.Path.Assets + "/bus5.png").ToSource(),
				Width = 20,
				Height = 16
			}.AttachTo(Bus1);

			Bus1.MoveTo(Bus1x, y);

			(1000 / 15).AtInterval(
				delegate
				{
					Bus1x -= 0.04;
					if (Bus1x <= 0.5)
						Bus1x = this.Playground.SizeX - 0.5;

					Bus1.MoveTo(Bus1x, y);
				}
			);
		}

		[Script]
		public class Tree1
		{
			Random BuildTree1Random = new Random();

			public int CurrentAge;
			public int MaxAge = 20;

			public Action<int> SetFrame;

			public readonly IsometricContainer.Sprite TreeSprite;

			public event Action Dead;

			public Tree1(IsometricContainerTile TreeLand)
			{
				var Tree1 = new IsometricContainer.Sprite(TreeLand.Context, 22, 38);
				this.TreeSprite = Tree1;

				var state = "abcdefg";

				var frames = Enumerable.Range(0, state.Length - 1).ToArray(
					i => new Image
					{
						Source = (KnownAssets.Path.Assets + "/tree1" + state.Substring(i, 1) + ".png").ToSource(),
						Width = 22,
						Height = 38,
						Visibility = Visibility.Hidden
					}.AttachTo(Tree1)
				);


				CurrentAge = MaxAge.Random();

				Tree1.MoveTo(TreeLand.X + BuildTree1Random.NextDouble(), TreeLand.Y - BuildTree1Random.NextDouble());

				var AgeTimer = default(DispatcherTimer);
				var Dispose = default(Action);
				Dispose =
					delegate
					{
						if (AgeTimer != null)
							AgeTimer.Stop();

						Tree1.OrphanizeContainer();
						TreeLand.Cleared -= Dispose;

						if (Dead != null)
							Dead();
					};

				TreeLand.Cleared += Dispose;

				var cframe = frames.RandomIndex();

				frames[cframe].Show();

				SetFrame =
					value =>
					{
						frames[cframe].Hide();
						cframe = value;
						if (cframe < frames.Length)
						{
							frames[cframe].Show();
						}
					};
				AgeTimer = 2000.AtIntervalWithTimer(
					t =>
					{
						CurrentAge++;

						if (CurrentAge < MaxAge)
						{
							return;
						}

						CurrentAge = 0;

						SetFrame(cframe + 1);

						if (cframe < frames.Length)
						{
							return;
						}

						Dispose();
					}
				);
			}
		}

		public event Action DeadTree;

		public void BuildTree1(IsometricContainerTile TreeLand)
		{
			new Tree1(TreeLand).Dead +=
			delegate
			{
				if (DeadTree != null) DeadTree();
			};
		}

		public event Action<int, IsometricContainerTile> BeforeVisualizeCost;

		public void VisualizeCost(int Cost, IsometricContainerTile Tile)
		{
			if (BeforeVisualizeCost != null)
				BeforeVisualizeCost(Cost, Tile);

			var sign = new IsometricContainer.Sprite(this.Playground, 64, 14)
			{
				//IgnoreZIndex = true,
				IsOverlay = true,
				Altitude = 0
			};

			var signc = new TycoonButton(64, 14);
			//signc.Text = "▲▼ 1";
			signc.Text = Cost.ToDollarString();
			if (Cost < 0)
				signc.Foreground = 0xffff0000.ToSolidColorBrush();
			else
				signc.Foreground = 0xff00ff00.ToSolidColorBrush();

			signc.BackgroundContainer.Hide();
			signc.AttachContainerTo(sign);

			sign.MoveTo(Tile);

			(1000 / 12).AtIntervalWithTimer(
				t =>
				{
					sign.Altitude++;

					if (sign.Altitude > 30)
					{
						t.Stop();
						signc.OrphanizeContainer();
					}
				}
			);
		}

		public void VisualizeError(string ErrorText, IsometricContainerTile Tile)
		{
	
			var sign = new IsometricContainer.Sprite(this.Playground, 64, 14)
			{
				//IgnoreZIndex = true,
				IsOverlay = true,
				Altitude = 0
			};

			var signc = new TycoonButton(64, 14);
			//signc.Text = "▲▼ 1";
			signc.Text = ErrorText;
			signc.Foreground = 0xffff0000.ToSolidColorBrush();


			signc.BackgroundContainer.Hide();
			signc.AttachContainerTo(sign);

			sign.MoveTo(Tile);

			(1000 / 12).AtIntervalWithTimer(
				t =>
				{
					sign.Altitude++;

					if (sign.Altitude > 40)
					{
						t.Stop();
						signc.OrphanizeContainer();
					}
				}
			);
		}

	}


	[Script]
	public static class PlaygroundBuilderExtensions
	{
		public static void BuildTo(this IsometricContainer.TileDescription value, IEnumerable<IsometricContainerTile> target)
		{
			target.ForEach(k => k.Description = value);
		}
	}
}
